package cn.dinkevin.xui.widget.input;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.InputFilter;
import android.text.Layout;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewTreeObserver;
import android.widget.EditText;

import cn.dinkevin.xui.R;

/**
 * Created by ycyca on 2018/4/24.
 * 带统计和字数限制的editText
 */

public class StatisticsEditText extends EditText {
    private EditText edit;
    private Paint mPaint;//画笔
    private Rect mBound;//文本绘制的范围
    private int editWidth;//输入框的宽高
    private int editHeight;

    private int numLength = 400;
    private String numStr = "0    /"+numLength;//咳咳，没空格字数到百位了绘制的字数统计就撮到屏幕外面去了，有更好的方式的话请指教
    private int numSize = R.dimen.y28;//字数统计的大小
    private final int MOVE_SLOP = 20; //移动距离临界

    //滑动距离的最大边界
    private int mOffsetHeight;

    //是否到顶或者到底的标志
    private boolean mBottomFlag = false;
    private boolean isCanScroll = false;//标记内容是否触发了滚动
    private float lastY = 0;
    public StatisticsEditText(Context context) {
        this(context,null);
    }
    public StatisticsEditText(Context context, AttributeSet attrs) {
        super(context,attrs);
        edit = this;
        //设置最多输入的字数
        edit.setFilters(new InputFilter[]{new InputFilter.LengthFilter(numLength)});
        mPaint = new Paint();
        int colorGray = getResources().getColor(R.color.normal_three);
        mPaint.setColor(colorGray);
        mPaint.setTextSize(numSize);
        mBound = new Rect();
        //初始化时候获取统计str的最小矩形的长宽。
        mPaint.getTextBounds(numStr, 0, numStr.length(), mBound);
        edit.setPadding(10, 0, 30, 10);

        //因为在绘制之前就会得到控件的宽高，即0和0，所以要强制在绘制完成之后再拿一次宽高才有正确数值
        ViewTreeObserver viewTreeObserver = this.getViewTreeObserver();
        viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                edit.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                editWidth = edit.getWidth();
                editHeight = edit.getHeight();
            }
        });
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制字数统计
        //-10 -5真的是无奈，px微调的话适配应该问题不大吧╮(╯▽╰)╭
        canvas.drawText(numStr, editWidth-mBound.width()-10, editHeight-mBound.height()-5, mPaint);
    }
    @Override
    protected void onTextChanged(CharSequence text, int start,
                                 int lengthBefore, int lengthAfter) {
//      super.onTextChanged(text, start, lengthBefore, lengthAfter);
        editHeight = getHeight();//目的在edit输入到第二行的时候刷新一下edit的高度重绘字数统计的高度
        int num = text.length();
        numStr = num+"/"+numLength;
        /*刷新该界面
         * invalidate()是用来刷新View的，必须是在UI线程中进行工作。
         * invalidate()得在UI线程中被调动，在工作者线程中可以通过Handler来通知UI线程进行界面更新。
         *而postInvalidate()在工作者线程中被调用
         * */
        postInvalidate();
        //重绘
        //requestLayout(); 区别在于绘制时候会不会重新测量位置即onMeaure，这个会重新归整位置
        invalidate();
    }
    public void setEditHint(String str){
        edit.setHint(str);
        //重绘
        requestLayout();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int paddingTop;
        int paddingBottom;
        int mHeight;
        int mLayoutHeight;

        //获得内容面板
        Layout mLayout = getLayout();
        mLayoutHeight = mLayout.getHeight();

        paddingTop = getTotalPaddingTop();
        paddingBottom = getTotalPaddingBottom();

        //获得控件的实际高度
        mHeight = getHeight();

        //计算滑动距离的边界(H_content - H_view = H_scroll)
        mOffsetHeight = mLayoutHeight + paddingTop + paddingBottom - mHeight;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN){
            //手指按下事件，重置状态
            mBottomFlag = false;
            isCanScroll = false;
            lastY=0;
        }
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean result = super.onTouchEvent(event);
        //如果是需要拦截，则再拦截，这个方法会在onScrollChanged方法之后再调用一次
        if (!mBottomFlag)
            getParent().requestDisallowInterceptTouchEvent(true);
        if (event.getAction() == MotionEvent.ACTION_MOVE){
            if (lastY == 0){
                lastY = event.getRawY();
            }
            //条件：手指move了一段距离，但是onScrollChanged函数未调用，说明文字无法滚动了，则将触摸处理权交还给ParentView
            if (Math.abs(lastY - event.getRawY()) > MOVE_SLOP){
                if (!isCanScroll){
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
            }
            //Log.d("Javine","ActionMove: "+ lastY + "," + event.getRawY());
        }
        return result;
    }

    @Override
    protected void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) {
        super.onScrollChanged(horiz, vert, oldHoriz, oldVert);
        isCanScroll = true;
        //Log.d("Javine","onScrolled "+vert);
        if (vert == mOffsetHeight || vert == 0) {
            //这里将处理权交还给父控件
            getParent().requestDisallowInterceptTouchEvent(false);
            mBottomFlag = true;
        }
    }
}